Material UIのTextFieldで’Type ‘”filled”‘ is not assignable to type ‘”outlined””.が発生する際の対処
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、Material UIのTextFieldでType 'Type '"filled"' is not assignable to type '"outlined"'.'
という型エラーが発生する際の対処についてです。
Material UIのTextFieldとは
React向けのUIライブラリであるMaterial UIでは、様々なMaterial Designベースのコンポーネントを使用できます。
そのコンポーネントのうちの一つであるTextFieldを使用すると、入力フォームやテーブルのフィルター画面などに利用できるコンポーネントを簡単に導入できます。
このTextFieldでは、variant
フィールドを指定することにより、コンポーネントの見た目を変えることができます。
import * as React from 'react'; import Box from '@mui/material/Box'; import TextField from '@mui/material/TextField'; export default function BasicTextFields() { return ( <Box component="form" sx={{ '& > :not(style)': { m: 1, width: '25ch' }, }} noValidate autoComplete="off" > <TextField id="outlined-basic" label="Outlined" variant="outlined" /> <TextField id="filled-basic" label="Filled" variant="filled" /> <TextField id="standard-basic" label="Standard" variant="standard" /> </Box> ); }
そして今回事象が発生したのはこのvariant
フィールドの扱いにおいてでした。
環境
事象が発生した環境は次のようになります。
@material-ui/core@4.11.0 @types/react@16.9.41 react@16.13.1 typescript@3.7.5
ここで注意点として、従来のMaterial UI(v4)は、2021年にMUI(Material UI v5)に置き換えられました。
The package names have changed in v5, which is a breaking change.
そして従来の@material-ui/coreはすでにメンテナンスが停止されています。よって新規プロジェクトでMaterial UIを導入する場合は、@material-ui/coreではなく、@mui/material を使うようにしましょう。
TextFieldのvariantフィールドで型エラーが発生する
さて前節の環境でTextFieldを使用して次のようなコンポーネントを作成しました。簡易化していますが、TextFieldのvariant
をstateに応じてfilled
とoutlined
で切り替えるようにしています。
import React from 'react'; import TextField from '@material-ui/core/TextField'; import Grid from '@material-ui/core/Grid'; import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles({ gridItem: { marginTop: '10px', }, }); let state = true; const App: React.FC = () => { const classes = useStyles(); return ( <Grid container alignItems='center' justify='center' direction='column' style={{ minHeight: '100vh' }} > <Grid item className={classes.gridItem}> <TextField id='field1' label='Field 1' variant='outlined' /> </Grid> <Grid item className={classes.gridItem}> <TextField id='field2' label='Field 2' variant='outlined' /> </Grid> <Grid item className={classes.gridItem}> <TextField id='field3' label='Field 3' variant={state ? 'filled' : 'outlined'} /> </Grid> </Grid> ); }; export default App;
このコンポーネントを含めたアプリをnpm run start
でローカル実行したところ、ビルド時に次のようなエラーが発生してしましいます。
Type '{ id: string; label: string; defaultValue: string; variant: "filled" | "outlined"; required: true; InputProps: { readOnly: boolean; }; }' is not assignable to type '(IntrinsicAttributes & StandardTextFieldProps) | (IntrinsicAttributes & FilledTextFieldProps) | (IntrinsicAttributes & OutlinedTextFieldProps)'. Type '{ id: string; label: string; defaultValue: string; variant: "filled" | "outlined"; required: true; InputProps: { readOnly: boolean; }; }' is not assignable to type 'OutlinedTextFieldProps'. Types of property 'variant' are incompatible. Type '"filled" | "outlined"' is not assignable to type '"outlined"'. Type '"filled"' is not assignable to type '"outlined"'. TS2322
解決
TextFieldのPropsは'(IntrinsicAttributes & StandardTextFieldProps) | (IntrinsicAttributes & FilledTextFieldProps) | (IntrinsicAttributes & OutlinedTextFieldProps)
となるところ、variant: "filled" | "outlined
の部分が上手く型付けできていないようです。
本来は問題無さそうですがバグのような動作です。
方法1
無理やりですがany
にキャストすることによりエラーを回避することができました。
<Grid item className={classes.gridItem}> <TextField id='field3' label='Field 3' variant={flag ? 'filled' : ('outlined' as any)} /> </Grid>
アプリも起動できています。
しかし環境によってはLintツールに引っかかるかも知れません。
方法2
TypeScriptをアップデートすることでも回避できました。今回は3.7.5
から4.5.5
にアップデートすることによりエラーは発生しなくなりました。
typescript@4.5.5
おわりに
Material UIのTextFieldでType 'Type '"filled"' is not assignable to type '"outlined"'.'
という型エラーが発生する際の対処についてでした。
解決まで少々時間を費やしてしまったのですが、明らかに怪しい動作に遭遇した際はライブラリのアップデートも選択肢に入れてすぐに試せると良いなと思いました。
参考
以上